package ldh.im.base.handler;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import ldh.im.dto.base.Dto;
import ldh.im.dto.base.WeightDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.PriorityQueue;

public class PriorityQueueHandler extends ChannelOutboundHandlerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(PriorityQueue.class);

    private PriorityQueue<Dto> responsePriorityQueue = new PriorityQueue<Dto>(this::comparator);
    private boolean isEmpty = true;

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (isEmpty) {
            isEmpty = false;
            ctx.write(msg, promise);
            promise.addListener(c->{
                if (c.isDone()) {
                    pollNext(ctx);
                }
            });
        } else {
            if (msg instanceof Dto) {
                responsePriorityQueue.add((Dto) msg);
                LOGGER.info("队列长度：{}", responsePriorityQueue.size());
            } else {
                ctx.write(msg, promise);
            }
        }
    }

    private int comparator(Dto dto1, Dto dto2) {
        if (dto1 instanceof WeightDto && dto2 instanceof WeightDto) {
            WeightDto r1 = (WeightDto) dto1;
            WeightDto r2 = (WeightDto) dto2;
            return r2.getWeight().compareTo(r1.getWeight());
        }
        return 0;
    }

    private void pollNext(ChannelHandlerContext ctx) {
        Dto response  = responsePriorityQueue.poll();
        if (response != null) {
            LOGGER.info("队列长度：{}, 获取数据：{}", responsePriorityQueue.size(), response.getClass().getSimpleName());
            ChannelFuture cc = ctx.write(response);
            cc.addListener(c->{
                if(c.isDone()) {
                    pollNext(ctx);
                }
            });
        } else {
            isEmpty = true;
        }
    }
}
